package com.volunteer.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.volunteer.common.BusinessException;
import com.volunteer.common.ResultCode;
import com.volunteer.entity.Activity;
import com.volunteer.entity.Registration;
import com.volunteer.entity.User;
import com.volunteer.mapper.ActivityMapper;
import com.volunteer.mapper.RegistrationMapper;
import com.volunteer.mapper.UserMapper;
import com.volunteer.service.BlackUserService;
import com.volunteer.service.RegistrationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 活动报名服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RegistrationServiceImpl extends ServiceImpl<RegistrationMapper, Registration> implements RegistrationService {

    private final ActivityMapper activityMapper;
    private final UserMapper userMapper;
    private final BlackUserService blackUserService;

    /**
     * 用户报名活动
     *
     * @param activityId 活动ID
     * @param userId     用户ID
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean register(Long activityId, Long userId) {
        if (activityId == null || userId == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR);
        }

        // 检查活动是否存在
        Activity activity = activityMapper.selectById(activityId);
        if (activity == null) {
            throw new BusinessException(ResultCode.NOT_FOUND);
        }

        // 检查用户是否存在
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException(ResultCode.USER_ACCOUNT_NOT_EXIST);
        }
        // 检查用户是否在黑名单
        boolean b = blackUserService.isUserInBlacklist(userId);
        if (b) {
            throw new BusinessException("您已被拉黑，无法报名");
        }

        // 检查活动状态
        if (activity.getStatus() == 4) {
            throw new BusinessException("活动已取消");
        }

        // 检查报名时间
        LocalDateTime now = LocalDateTime.now();
        if (now.isAfter(activity.getRegisterStartTime())) {
            throw new BusinessException("报名未开始");
        }

        // 检查是否已满员
        if (activity.getRegisteredNumber() <= activity.getRecruitNumber()) {
            throw new BusinessException(ResultCode.ACTIVITY_FULL);
        }

        // 检查是否已报名
        if (isUserRegistered(activityId, userId)) {
            throw new BusinessException(ResultCode.ACTIVITY_ALREADY_REGISTERED);
        }

        // 创建报名记录
        Registration registration = new Registration();
        registration.setActivityId(activityId);
        registration.setUserId(userId);
        registration.setStatus(0); // 待审核
        registration.setRegisterTime(now);
        registration.setCheckInStatus(0); // 未签到
        registration.setIsEvaluated(0); // 未评价

        // 更新活动报名人数
        activity.setRecruitNumber(activity.getRecruitNumber() + 1);
        activityMapper.updateById(activity);

        return this.save(registration);
    }

    /**
     * 取消报名
     *
     * @param registrationId 报名ID
     * @param userId         用户ID
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelRegistration(Long registrationId, Long userId) {
        if (registrationId == null || userId == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR);
        }

        // 检查报名是否存在
        Registration registration = this.getById(registrationId);
        if (registration == null) {
            throw new BusinessException(ResultCode.NOT_FOUND);
        }

        // 检查是否是本人操作
        if (!registration.getUserId().equals(userId)) {
            throw new BusinessException(ResultCode.FORBIDDEN);
        }

        // 检查活动是否存在
        Activity activity = activityMapper.selectById(registration.getActivityId());
        if (activity == null) {
            throw new BusinessException(ResultCode.NOT_FOUND);
        }

        // 检查是否已签到或已结束
        if (registration.getCheckInStatus() == 1) {
            throw new BusinessException("已签到的报名不能取消");
        }
        if (activity.getStatus() == 3) {
            throw new BusinessException("已结束的活动不能取消报名");
        }

        // 更新报名状态
        registration.setStatus(3); // 已取消
        boolean result = this.updateById(registration);

        // 更新活动报名人数
        if (registration.getStatus() == 1) { // 之前是已通过状态才减少招募人数
            activity.setRegisteredNumber(activity.getRegisteredNumber() - 1);
            activityMapper.updateById(activity);
        }

        return result;
    }

    /**
     * 审核报名
     *
     * @param registrationId 报名ID
     * @param status         状态（1-通过 2-拒绝）
     * @param remark         备注
     * @param operatorId     操作人ID
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean auditRegistration(Long registrationId, Integer status, String remark, Long operatorId) {
        if (registrationId == null || status == null || operatorId == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR);
        }

        // 检查报名是否存在
        Registration registration = this.getById(registrationId);
        if (registration == null) {
            throw new BusinessException(ResultCode.NOT_FOUND);
        }

        // 检查活动是否存在
        Activity activity = activityMapper.selectById(registration.getActivityId());
        if (activity == null) {
            throw new BusinessException(ResultCode.NOT_FOUND);
        }

        // 检查操作人权限
        if (!activity.getCreatorId().equals(operatorId)) {
            User operator = userMapper.selectById(operatorId);
            if (operator == null || operator.getRole() != 2) { // 不是管理员
                throw new BusinessException(ResultCode.FORBIDDEN);
            }
        }

        // 检查活动状态
        if (activity.getStatus() == 3 || activity.getStatus() == 4) {
            throw new BusinessException("已结束或已取消的活动不能审核报名");
        }

        // 检查报名状态
        if (registration.getStatus() == 3) {
            throw new BusinessException("已取消的报名不能审核");
        }

        // 更新报名状态
        registration.setStatus(status);
        registration.setAuditTime(LocalDateTime.now());
        registration.setAuditRemark(remark);
        boolean result = this.updateById(registration);

        return result;
    }

    /**
     * 签到
     *
     * @param registrationId 报名ID
     * @param operatorId     操作人ID
     * @return 是否成功
     */
    @Override
    public boolean checkIn(Long registrationId, Long operatorId) {
        if (registrationId == null || operatorId == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR);
        }

        // 检查报名是否存在
        Registration registration = this.getById(registrationId);
        if (registration == null) {
            throw new BusinessException(ResultCode.NOT_FOUND);
        }

        // 检查活动是否存在
        Activity activity = activityMapper.selectById(registration.getActivityId());
        if (activity == null) {
            throw new BusinessException(ResultCode.NOT_FOUND);
        }

        // 检查操作人权限
        if (!activity.getCreatorId().equals(operatorId)) {
            User operator = userMapper.selectById(operatorId);
            if (operator == null || operator.getRole() != 2) { // 不是管理员
                throw new BusinessException(ResultCode.FORBIDDEN);
            }
        }

        // 检查报名状态
        if (registration.getStatus() != 1) {
            throw new BusinessException("只有已通过的报名才能签到");
        }

        // 检查是否已签到
        if (registration.getCheckInStatus() == 1) {
            throw new BusinessException("已签到");
        }

        // 更新签到状态
        registration.setCheckInStatus(1);
        registration.setCheckInTime(LocalDateTime.now());
        // 增加该用户学分
        userMapper.addScores(registration.getUserId(), 1);
        return this.updateById(registration);
    }


    /**
     * 分页查询活动的报名列表
     *
     * @param page       分页参数
     * @param activityId 活动ID
     * @param status     状态
     * @return 报名列表
     */
    @Override
    public Page<Registration> pageActivityRegistrations(Page<Registration> page, Long activityId, Integer status) {
        if (activityId == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR);
        }

        LambdaQueryWrapper<Registration> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Registration::getActivityId, activityId);

        if (status != null) {
            queryWrapper.eq(Registration::getStatus, status);
        }

        queryWrapper.orderByDesc(Registration::getRegisterTime);

        return this.page(page, queryWrapper);
    }

    /**
     * 分页查询用户的报名列表
     *
     * @param page   分页参数
     * @param userId 用户ID
     * @param status 状态
     * @return 报名列表
     */
    @Override
    public Page<Registration> pageUserRegistrations(Page<Registration> page, Long userId, Integer status) {
        if (userId == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR);
        }

        LambdaQueryWrapper<Registration> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Registration::getUserId, userId);

        if (status != null) {
            queryWrapper.eq(Registration::getStatus, status);
        }

        queryWrapper.orderByDesc(Registration::getRegisterTime);

        return this.page(page, queryWrapper);
    }

    @Override
    public Page<Registration> getUserRegistrationListWithDetail(Page<Registration> page, Long userId, Integer status, String title) {
        if (userId == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR);
        }

        return baseMapper.getUserRegistrationListWithDetail(page, userId, status, title);
    }

    /**
     * 查询用户是否已报名活动
     *
     * @param activityId 活动ID
     * @param userId     用户ID
     * @return 是否已报名
     */
    @Override
    public boolean isUserRegistered(Long activityId, Long userId) {
        if (activityId == null || userId == null) {
            return false;
        }

        LambdaQueryWrapper<Registration> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Registration::getActivityId, activityId)
                .eq(Registration::getUserId, userId)
                .ne(Registration::getStatus, 3); // 非取消状态

        return this.count(queryWrapper) > 0;
    }

    /**
     * 查询用户的报名
     *
     * @param activityId 活动ID
     * @param userId     用户ID
     * @return 报名信息
     */
    @Override
    public Registration getUserRegistration(Long activityId, Long userId) {
        if (activityId == null || userId == null) {
            return null;
        }

        LambdaQueryWrapper<Registration> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Registration::getActivityId, activityId)
                .eq(Registration::getUserId, userId);

        return this.getOne(queryWrapper);
    }

    @Override
    public List<Activity> getRegisteredActivitiesByUserId(Long userId) {
        List<Registration> registers = this.list(new LambdaQueryWrapper<Registration>().eq(Registration::getUserId, userId));
        List<Long> activityIds = registers.stream().map(Registration::getActivityId).collect(Collectors.toList());
        if (activityIds.isEmpty()) return List.of();
        return activityMapper.selectBatchIds(activityIds);
    }

    @Override
    public boolean userCheckIn(Long registrationId, Long userId) {
        if (registrationId == null || userId == null) {
            throw new BusinessException(ResultCode.PARAM_ERROR);
        }

        // 检查报名是否存在
        Registration registration = this.getById(registrationId);
        if (registration == null) {
            throw new BusinessException(ResultCode.NOT_FOUND);
        }

        // 验证用户身份
        if (!registration.getUserId().equals(userId)) {
            throw new BusinessException("只能为自己签到");
        }

        // 检查报名状态
        if (registration.getStatus() != 1) {
            throw new BusinessException("只有审核通过的报名才能签到");
        }

        // 检查是否已签到
        if (registration.getCheckInStatus() == 1) {
            throw new BusinessException("已签到，请勿重复操作");
        }

        // 检查活动是否存在
        Activity activity = activityMapper.selectById(registration.getActivityId());
        if (activity == null) {
            throw new BusinessException(ResultCode.NOT_FOUND);
        }

        // 检查活动是否已开始
        LocalDateTime now = LocalDateTime.now();
        if (now.isAfter(activity.getStartTime())) {
            throw new BusinessException("活动尚未开始，无法签到");
        }

        // 检查活动是否已结束
        if (activity.getStatus() == 3 || activity.getStatus() == 4) {
            throw new BusinessException("活动已结束或已取消，无法签到");
        }

        // 更新签到状态
        registration.setCheckInStatus(1);
        registration.setCheckInTime(LocalDateTime.now());

        // 增加该用户学分 - 10分
        userMapper.addScores(registration.getUserId(), 10);

        return this.updateById(registration);
    }

}
